package com.junxonline.instant.common.util.terminal;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Netty Channel工具类
 *
 * @author JunX
 * @date 2021-09-03
 */
public class NettyChannelUtils {

    /**
     * Channel容器
     */
    private final static DefaultChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 客户端容器（线程安全）
     */
    private final static ConcurrentMap<String, ChannelId> terminals = new ConcurrentHashMap<>();

    /**
     * 添加一个客户端连接通道
     *
     * @param terminalCode 终端编号
     * @param channel      连接通道
     */
    public static void addChannel(String terminalCode, Channel channel) {
        channels.add(channel);
        terminals.put(terminalCode, channel.id());
    }

    /**
     * 移除一个客户端连接通道
     *
     * @param terminalCode 终端编号
     */
    public static void removeChannel(String terminalCode) {
        Channel channel = getChannel(terminalCode);
        channels.remove(channel);
        terminals.remove(terminalCode);
    }

    /**
     * 移除一个客户端连接通道
     *
     * @param channel 连接通道
     */
    public static void removeChannel(Channel channel) {
        channels.remove(channel);
    }

    /**
     * 获取一个客户端连接通道
     *
     * @param terminalCode 终端编号
     * @return Channel
     */
    public static Channel getChannel(String terminalCode) {
        ChannelId channelId = terminals.get(terminalCode);
        return channelId != null ? channels.find(channelId) : null;
    }

    /**
     * 判断容器中是否包含某个客户端连接通道
     *
     * @param terminalCode 终端编号
     * @return Channel
     */
    public static boolean hasChannel(String terminalCode) {
        return getChannel(terminalCode) != null;
    }

    /**
     * 获取终端编号
     * @param channelId 连接通道ID
     * @return String
     */
    public static String getTerminalCode(ChannelId channelId) {
        Channel channel = channels.find(channelId);
        for (Map.Entry<String, ChannelId> entry : terminals.entrySet()) {
            String key = entry.getKey();
            ChannelId value = entry.getValue();
            if (value.equals(channelId)) {
                return key;
            }
        }
        return null;
    }

    /**
     * 发送单条消息
     *
     * @param terminalCode 终端编号
     * @param jsonMessage  消息内容（JSON）
     */
    public static void sendSingleMessage(String terminalCode, String jsonMessage) {
        Channel channel = getChannel(terminalCode);
        if (channel != null) {
            channel.writeAndFlush(new TextWebSocketFrame(jsonMessage));
        }
    }

    /**
     * 发送全体消息
     *
     * @param jsonMessage 消息内容（JSON）
     */
    public static void sendAllMessage(String jsonMessage) {
        channels.writeAndFlush(new TextWebSocketFrame(jsonMessage));
    }

}
